﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Cinchoo.Core.IO;
using Cinchoo.Core.Collections;
using System.IO;
using System.Collections;

namespace Cinchoo.Core.ETL
{
    public class ChoETLCSVFileLoaderTask : ChoETLTask
    {
        #region Instance Data Members (Private)

        protected string _filePath;
        protected string _seperator = ",";

        public bool IsFirstLineHeader
        {
            get;
            set;
        }
        public string[] CommentTokens { get; set; }

        #endregion Instance Data Members (Private)

        #region Constructors

        public ChoETLCSVFileLoaderTask(string filePath = null, string seperator = null)
        {
            _filePath = filePath;
            if (!seperator.IsNullOrWhiteSpace())
                _seperator = seperator;
        }

        #endregion Constructors

        #region ChoETLFileLoadTask Overridables

        protected override bool Initialize()
        {
            ChoGuard.ArgumentNotNullOrEmpty(_filePath, "FilePath");

            if (!File.Exists(_filePath))
                throw new ChoETLException("{0} is not a valid file path.".FormatString(_filePath));

            Log("Opening '{0}' CSV file".FormatString(_filePath));

            return base.Initialize();
        }

        protected override IEnumerable<IEnumerable<ChoETLObject>> ExecuteTask(IEnumerable<IEnumerable<ChoETLObject>> lists)
        {
            ChoCSVFileReadEnumerator e = new ChoCSVFileReadEnumerator(_filePath, _seperator);
            e.IsFirstLineHeader = IsFirstLineHeader;
            e.CommentTokens = CommentTokens;
            yield return new ChoEnumerable<ChoETLScalarObject>(e);
        }

        #endregion ChoETLFileLoadTask Overridables

        #region ChoCSVFileReadEnumerator class

        private class ChoCSVFileReadEnumerator : IEnumerator<ChoETLScalarObject>
        {
            private readonly string _filePath;
            private readonly string _seperator;
            private StreamReader _sr;
            private string _line;

            public bool IsFirstLineHeader
            {
                get;
                set;
            }

            public string[] CommentTokens
            {
                get;
                set;
            }

            public ChoCSVFileReadEnumerator(string filePath, string seperator)
            {
                _filePath = filePath;
                _seperator = seperator;
                Reset();
            }

            public ChoETLScalarObject Current
            {
                get {
                    int i = 0;
                    return new ChoETLScalarObject(
                    (from item in _line.Split(_seperator)
                    select new KeyValuePair<string, object>(i++.ToString(), item)).ToArray()); }
            }

            public void Dispose()
            {
                _sr.Dispose();
            }

            object IEnumerator.Current
            {
                get { return Current; }
            }

            public bool MoveNext()
            {
                _line = ReadLine();
                if (_line == null)
                    return false;
                else
                    return true;
            }

            private string ReadLine()
            {
                if (CommentTokens == null)
                    return _sr.ReadLine();
                else
                {
                    string line = null;
                    while (true)
                    {
                        line = _sr.ReadLine();
                        if (line == null)
                            break;

                        var x = (from c in CommentTokens
                                 where line.StartsWith(c)
                                 select c).FirstOrDefault();
                        if (x == null)
                            break;
                    }

                    return line;
                }
            }
            public void Reset()
            {
                _sr = new StreamReader(_filePath);
                if (IsFirstLineHeader)
                    _sr.ReadLine();
            }
        }

        #endregion ChoCSVFileReadEnumerator class
    }
}
